﻿using MaterialDesignThemes.Wpf;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace YoutubeDl.Wpf.Models;

public class ObservableSettings(Settings settings) : ReactiveObject
{
    public Settings AppSettings { get; } = settings;

    public BaseTheme AppColorMode { get; set; } = settings.AppColorMode;

    [Reactive]
    public double WindowWidth { get; set; } = settings.WindowWidth;

    [Reactive]
    public double WindowHeight { get; set; } = settings.WindowHeight;

    [Reactive]
    public BackendTypes Backend { get; set; } = settings.Backend;

    [Reactive]
    public string BackendPath { get; set; } = settings.BackendPath;

    /// <summary>
    /// Gets or sets the list of arguments passed
    /// to the backend process for all types of operations.
    /// </summary>
    public ObservableCollection<BackendArgument> BackendGlobalArguments { get; set; } = new(settings.BackendGlobalArguments);

    /// <summary>
    /// Gets or sets the list of arguments passed
    /// to the backend process for download operations.
    /// </summary>
    public List<BackendArgument> BackendDownloadArguments { get; set; } = new(settings.BackendDownloadArguments);

    [Reactive]
    public bool BackendAutoUpdate { get; set; } = settings.BackendAutoUpdate;

    [Reactive]
    public DateTimeOffset BackendLastUpdateCheck { get; set; } = settings.BackendLastUpdateCheck;

    [Reactive]
    public string FfmpegPath { get; set; } = settings.FfmpegPath;

    [Reactive]
    public string Proxy { get; set; } = settings.Proxy;

    [Reactive]
    public int LoggingMaxEntries { get; set; } = settings.LoggingMaxEntries;

    [Reactive]
    public Preset? SelectedPreset { get; set; } = settings.SelectedPreset;

    /// <summary>
    /// This is a hack to prevent <see cref="SelectedPreset"/> from being changed to null.
    /// Another solution is to manually implement equality for <see cref="Preset"/>,
    /// which is much harder to get it right, and would look terrible compared to this little hack.
    /// </summary>
    [Reactive]
    public string SelectedPresetText { get; set; } = settings.SelectedPreset.DisplayName;

    public List<Preset> CustomPresets { get; set; } = new(settings.CustomPresets);

    [Reactive]
    public bool AddMetadata { get; set; } = settings.AddMetadata;

    [Reactive]
    public bool DownloadThumbnail { get; set; } = settings.DownloadThumbnail;

    [Reactive]
    public bool DownloadSubtitles { get; set; } = settings.DownloadSubtitles;

    [Reactive]
    public bool DownloadSubtitlesAllLanguages { get; set; } = settings.DownloadSubtitlesAllLanguages;

    [Reactive]
    public bool DownloadAutoGeneratedSubtitles { get; set; } = settings.DownloadAutoGeneratedSubtitles;

    [Reactive]
    public bool DownloadPlaylist { get; set; } = settings.DownloadPlaylist;

    [Reactive]
    public bool UseCustomOutputTemplate { get; set; } = settings.UseCustomOutputTemplate;

    [Reactive]
    public string CustomOutputTemplate { get; set; } = settings.CustomOutputTemplate;

    /// <summary>
    /// Gets the list of used output templates.
    /// New templates are appended to the list.
    /// </summary>
    public List<string> OutputTemplateHistory { get; } = new(settings.OutputTemplateHistory);

    [Reactive]
    public bool UseCustomPath { get; set; } = settings.UseCustomPath;

    [Reactive]
    public string DownloadPath { get; set; } = settings.DownloadPath;

    /// <summary>
    /// Gets the list of used download paths.
    /// New paths are appended to the list.
    /// </summary>
    public List<string> DownloadPathHistory { get; } = new(settings.DownloadPathHistory);

    public void UpdateAppSettings()
    {
        AppSettings.AppColorMode = AppColorMode;
        AppSettings.WindowWidth = WindowWidth;
        AppSettings.WindowHeight = WindowHeight;
        AppSettings.Backend = Backend;
        AppSettings.BackendPath = BackendPath;
        AppSettings.BackendGlobalArguments = [.. BackendGlobalArguments];
        AppSettings.BackendDownloadArguments = [.. BackendDownloadArguments];
        AppSettings.BackendAutoUpdate = BackendAutoUpdate;
        AppSettings.BackendLastUpdateCheck = BackendLastUpdateCheck;
        AppSettings.FfmpegPath = FfmpegPath;
        AppSettings.Proxy = Proxy;
        // AppSettings.LoggingMaxEntries is managed by the validation handler.
        AppSettings.SelectedPreset = SelectedPreset ?? Preset.Auto;
        AppSettings.CustomPresets = [.. CustomPresets];
        AppSettings.AddMetadata = AddMetadata;
        AppSettings.DownloadThumbnail = DownloadThumbnail;
        AppSettings.DownloadSubtitles = DownloadSubtitles;
        AppSettings.DownloadSubtitlesAllLanguages = DownloadSubtitlesAllLanguages;
        AppSettings.DownloadAutoGeneratedSubtitles = DownloadAutoGeneratedSubtitles;
        AppSettings.DownloadPlaylist = DownloadPlaylist;
        AppSettings.UseCustomOutputTemplate = UseCustomOutputTemplate;
        AppSettings.CustomOutputTemplate = CustomOutputTemplate;
        AppSettings.UseCustomPath = UseCustomPath;
        AppSettings.OutputTemplateHistory = [.. OutputTemplateHistory];
        AppSettings.DownloadPath = DownloadPath;
        AppSettings.DownloadPathHistory = [.. DownloadPathHistory];
    }
}
